﻿using EShop.Net.Auth;
using EShop.Net.IServices.User;
using EShop.Net.Loging;
using EShop.Net.Model;
using EShop.Net.Model.Entity;
using EShop.Net.Model.FromBody;
using EShop.Net.Util.Date;
using EShop.Net.Util.Encrypt;
using EShop.Net.WeChar.Client;
using EShop.Net.WeChar.Encrypt;
using EShop.Net.WeChar.PhoneNumber;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using NLog;
using SKIT.FlurlHttpClient.Wechat.Api;
using SKIT.FlurlHttpClient.Wechat.Api.Models;
using System;
using System.Security.Claims;
using System.Threading.Tasks;

namespace EShop.Net.API.Controllers.User
{
    /// <summary>
    /// 用户表控制器
    /// </summary>
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class UserController : Controller
    {
        private IWebHostEnvironment evn { get; }
        private readonly IUserServices userIServices;

        public UserController(IWebHostEnvironment env, IUserServices userIServices)
        {
            this.evn = env;
            this.userIServices = userIServices;
        }

        /// <summary>
        /// 微信小程序登录
        /// </summary>
        /// <param name="entity">微信小程序登录实体</param>
        /// <returns>Token对象</returns>
        [HttpPost]
        public async Task<ResponseResultJson> Login([FromBody] FBWeixinLogin entity)
        {
            try
            {
                WechatApiClientFactory wechatApiClientFactory = new WechatApiClientFactory();
                var client = wechatApiClientFactory.CreateWxClient();
                var request = new SnsJsCode2SessionRequest()
                {
                    JsCode = entity.code,
                    AccessToken = ""
                };
                var response = await client.ExecuteSnsJsCode2SessionAsync(request, HttpContext.RequestAborted);
                TokenObj<UserInfo> token = null;
                if (response.ErrorCode == 0)
                {
                    var userInfo = await this.userIServices.SelectUserByOpenId(response.OpenId);
                    if (userInfo == null)
                    {
                        userInfo = new UserInfo()
                        {
                            openId = response.OpenId,
                            sessionKey = response.SessionKey,
                            unionId = response.UnionId,
                            nickName = entity.nickName,
                            avatarImage = entity.avatarUrl,
                            createTime = DateTimeHelper.BeijingTimeToUnixTimeStamp13(DateTime.Now),
                            gender = 3,
                            status = 0
                        };
                        await this.userIServices.InsertAsync(userInfo);
                    }
                    else
                    {
                        if (userInfo.sessionKey != response.SessionKey)
                        {
                            var res = await this.userIServices.UpdateByUserOpenid(response.OpenId, response.SessionKey, entity.nickName, entity.avatarUrl);
                        }
                    }
                    var userInfoList = await this.userIServices.QueryListByClauseAsync(u => u.openId.Equals(userInfo.openId));
                    Claim[] claims = new Claim[]
                    {
                        new Claim(ClaimTypes.Name, userInfoList[0].nickName),
                        new Claim(ClaimTypes.NameIdentifier, userInfoList[0].openId),
                        new Claim(ClaimTypes.Role, "USER")
                    };
                    token = JwtToken<UserInfo>.GetJwtToken(claims, evn.ContentRootPath, 1);
                    string[] encryptStrArr = userInfoList[0].userPhone.Split('。');
                    UserInfo userData = new UserInfo() 
                    {
                        id = userInfoList[0].id,
                        openId = userInfoList[0].openId,
                        nickName = userInfoList[0].nickName,
                        avatarImage = userInfoList[0].avatarImage,
                        city = userInfoList[0].city,
                        province = userInfoList[0].province,
                        district = userInfoList[0].district,
                        gender = userInfoList[0].gender,
                        userPhone = EncryptionHelper.MD5Decrypt(encryptStrArr[1], encryptStrArr[0]),
                        birthday = userInfoList[0].birthday,
                        status = userInfoList[0].status
                    };
                    token.userInfo = userData;
                }
                return ResponseResultJson.ResponseResult(200, "Token:OK", token);
            }
            catch (Exception ex)
            {
                NLogUtil.WriteAll(LogLevel.Error, LogType.UserLogin, "微信小程序登录", "Login控制器层", ex);
                return ResponseResultJson.ResponseResult(500, "Token:ERROR", ex.Message);
            }
        }

        /// <summary>
        /// 微信小程序解密手机号
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        [HttpPost]
        [Authorize(Roles = "USER")]
        public async Task<ResponseResultJson> WeixinDecryptPhone([FromBody] FBWeixinDecryptPhone entity)
        {
            try
            {
                var userInfo = await this.userIServices.QueryListByClauseAsync(u => u.openId == entity.sessionAuthId);
                if (userInfo.Count < 0 || userInfo == null)
                {
                    return ResponseResultJson.ResponseResult(2001, "用户信息获取失败", null);
                }
                // sessionKey 可能存在过期问题（微信官方不会把过期时间告诉开发者）
                DecodedPhoneNumber phoneNumber = EncryptHelper.DecryptPhoneNumber(userInfo[0].sessionKey, entity.encryptedData, entity.iv);
                return ResponseResultJson.ResponseResult(200, "OK", phoneNumber);
            }
            catch (Exception ex)
            {
                NLogUtil.WriteAll(LogLevel.Error, LogType.UserLogin, "微信小程序解密手机号", "WeixinDecryptPhone控制器层", ex);
                return ResponseResultJson.ResponseResult(500, "ERROR", ex.Message);
            }
        }

        /// <summary>
        /// 修改个人信息
        /// </summary>
        /// <param name="entity">修改个人信息参数实体</param>
        /// <returns></returns>
        [HttpPost]
        [Authorize(Roles = "USER")]
        public async Task<ResponseResultJson> UpdateUserInfo([FromBody] FBUpdateUserInfo entity)
        {
            try
            {
                var data = await this.userIServices.UpdateUserInfoById(entity.id, entity.birthday, entity.gender, entity.city, entity.province, entity.district, entity.userPhone);
                return ResponseResultJson.ResponseResult(200, "OK", data);
            }
            catch (Exception ex)
            {
                NLogUtil.WriteAll(LogLevel.Error, LogType.ApiRequest, "修改个人信息", "UpdateUserInfo控制器层", ex);
                return ResponseResultJson.ResponseResult(500, "ERROR", ex.Message);
            }
        }
    }
}
